package ring_buffer

import (
	"context"
	"sync"
)

// RingBuffer 默认覆盖策略：丢弃
type RingBuffer struct {
	queue    []interface{}
	writeIdx int
	readIdx  int
	size     int
	mu       sync.Mutex
}

func (r *RingBuffer) IsFull() bool {
	r.mu.Lock()
	defer r.mu.Unlock()
	return r.writeIdx == r.readIdx+r.size
}

func (r *RingBuffer) isFull() bool {
	return r.writeIdx == r.readIdx+r.size
}

func (r *RingBuffer) IsEmpty() bool {
	r.mu.Lock()
	defer r.mu.Unlock()
	// 不能用len(r.queue) 因为是环形 数组重复利用使用下标赋值,一开始创建make([]interface{}, size)时len=2
	return r.writeIdx == r.readIdx
}

func (r *RingBuffer) isEmpty() bool { // 内部使用
	return r.writeIdx == r.readIdx
}

func (r *RingBuffer) Read() (interface{}, error) {
	r.mu.Lock()
	defer func() {
		r.queue[r.readIdx%r.size] = nil // 重置，断开引用，保证GC可以回收掉该位置的数据
		r.readIdx++
		r.mu.Unlock()
	}()
	if r.isEmpty() {
		return nil, ErrQueueIsEmpty
	}
	return r.queue[r.readIdx%r.size], nil
}

func (r *RingBuffer) Write(ctx context.Context, v interface{}) error {
	r.mu.Lock()
	defer r.mu.Unlock()

	// 队列满的判断：r.writeIdx == r.readIdx + r.size 丢弃策略下writeIdx不会超圈readIdx
	if r.isFull() { // 丢弃
		return nil
	}
	r.queue[r.writeIdx%r.size] = v
	r.writeIdx++
	return nil
}

func NewRingBuffer(size int) Ring {
	return &RingBuffer{
		queue:    make([]interface{}, size),
		writeIdx: 0,
		readIdx:  0,
		size:     size,
	}
}

func newRingBufferV2(size int) *RingBuffer {
	return &RingBuffer{
		queue:    make([]interface{}, size),
		writeIdx: 0,
		readIdx:  0,
		size:     size,
	}
}

var _ Ring = (*RingBuffer)(nil)
var _ RingBufferCreator = NewRingBuffer
